package com.backend.modules.file.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.backend.common.exception.BusinessException;
import com.backend.config.oss.OssProperties;
import com.backend.modules.file.service.OssService;
import com.backend.modules.file.vo.OssTokenVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.Date;

@Service
@RequiredArgsConstructor
public class OssServiceImpl implements OssService {

    private final OssProperties ossProperties;

    @Override
    public OssTokenVO getToken(String directory) {
        try {
            // 创建RAM访问凭证
            DefaultProfile profile = DefaultProfile.getProfile(
                    ossProperties.getRegion(),
                    ossProperties.getAccessKeyId(),
                    ossProperties.getAccessKeySecret());
            DefaultAcsClient client = new DefaultAcsClient(profile);

            // 创建 AssumeRole 请求
            AssumeRoleRequest request = new AssumeRoleRequest();
            request.setMethod(MethodType.POST);
            request.setRoleArn(ossProperties.getRoleArn());
            request.setRoleSessionName("file-upload");
            request.setDurationSeconds(ossProperties.getDurationSeconds());

            // 获取 STS 凭证
            AssumeRoleResponse response = client.getAcsResponse(request);
            AssumeRoleResponse.Credentials credentials = response.getCredentials();

            // 生成上传策略
            String dir = ossProperties.getUploadDir() + directory;
            long expireTime = System.currentTimeMillis() + ossProperties.getDurationSeconds() * 1000;
            Date expiration = new Date(expireTime);

            OSS ossClient = new OSSClientBuilder().build(
                    ossProperties.getEndpoint(),
                    credentials.getAccessKeyId(),
                    credentials.getAccessKeySecret(),
                    credentials.getSecurityToken());

            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            ossClient.shutdown();

            // 返回上传凭证
            OssTokenVO tokenVO = new OssTokenVO();
            tokenVO.setAccessKeyId(credentials.getAccessKeyId());
            tokenVO.setAccessKeySecret(credentials.getAccessKeySecret());
            tokenVO.setSecurityToken(credentials.getSecurityToken());
            tokenVO.setExpiration(expireTime);
            tokenVO.setRegion(ossProperties.getRegion());
            tokenVO.setBucket(ossProperties.getBucketName());
            tokenVO.setDir(dir);
            tokenVO.setHost("https://" + ossProperties.getBucketName() + "." + ossProperties.getEndpoint());
            tokenVO.setPolicy(encodedPolicy);
            tokenVO.setSignature(postSignature);

            return tokenVO;
        } catch (ClientException e) {
            throw new BusinessException("获取上传凭证失败：" + e.getMessage());
        }
    }

    @Override
    public void deleteFile(String objectName) {
        OSS ossClient = new OSSClientBuilder().build(
                ossProperties.getEndpoint(),
                ossProperties.getAccessKeyId(),
                ossProperties.getAccessKeySecret());

        try {
            ossClient.deleteObject(ossProperties.getBucketName(), objectName);
        } finally {
            ossClient.shutdown();
        }
    }

    @Override
    public String generateFileUrl(String objectName) {
        return "https://" + ossProperties.getBucketName() + "." + 
               ossProperties.getEndpoint() + "/" + objectName;
    }
} 